/*
 * Iwire.cpp
 *
 *  Created on: 21.02.2013
 *      Author: Roma Jam
 */

#include "Iwire.h"
#include "led.h"

IWire_t IWire;

void IWire_t::Task(){
    switch (State) {
        case iwsIdle:
            break;

        case iwsPresence:
            Cmd(CMD_SKIP_ROM);
            Cmd(CMD_CONVERT_T);
            Delay.Reset(&Timer);
            State = iwsWaitAnsw;
//            Uart.Printf("iwsPresence\r");
            break;

        case iwsWaitAnsw:
            if(Delay.Elapsed(&Timer, 999)){
                Reset();
                Cmd(CMD_SKIP_ROM);
                Cmd(CMD_READ_SCRATCHPAD);
                Uart.Printf("wait\r");
                while(1);
            }
            break;

        case iwsReadyToConv:
            break;

        case iwsRxTemp:
            break;

        case iwsBusy:   // Line Idle and USART free
            if(Delay.Elapsed(&Timer, 10)) State = iwsAbsent;
            else {
//                Uart.Printf("iwsBusy: %A\r", PRXBuf, WriteIndx);
                if(PRXBuf[WriteIndx - 1] == 0xCD){
                    State = iwsPresence;
                    Uart.Printf("iwsPresence\r");
                }
                else if(PRXBuf[WriteIndx - 1] == 0xCF){
//                    Uart.Printf("iwsCF\r");
                    State = iwsAbsent;
                }
            } // Delay elapsed
            break;

        case iwsAbsent:
            // Search Again
            Reset();
            State = iwsBusy;
            break;
    } // switch
} // Task


void IWire_t::Init(){
    PRXBuf = RXBuf;
    PIndex = &WriteIndx;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    // ==== GPIO init ====
    GPIO_InitTypeDef GPIO_InitStructure;
    // Configure USART Tx as alternate function push-pull
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin   = UART2_TX;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(UART2_GPIO, &GPIO_InitStructure);
    // Configure USART Rx as input floating
//    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = UART2_RX;
    GPIO_Init(UART2_GPIO, &GPIO_InitStructure);

    // ==== USART configuration ====
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_2;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART2, &USART_InitStructure);
//    Enable RX interrupt
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);     // Configure the NVIC Preemption Priority Bits
    // Enable the USART Interrupt
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
//    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    // Enable RX interrupt
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

    // Enable USART
    USART_Cmd(USART2, ENABLE);

    BufInit();
    State = iwsAbsent;
    Count = 0;

    Speed = ssReg;
}

void IWire_t::ReInit(uint32_t AValue){
    USART_DeInit(USART2);
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = AValue;
    USART_Init(USART2, &USART_InitStructure);
}

void IWire_t::Cmd(uint8_t CMD){
    USART_SendData(USART2, CMD);
    while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
    Uart.Printf("--> %X \r", CMD);
}

void IWire_t::SendService(uint8_t AByte){
    for(uint8_t i = 0; i < 8; i++){
        if(AByte & 0x01) Cmd(0x80 | 0x10 | Speed);
        else Cmd(0x80 | 0x00 | Speed);
        AByte >>= 1;
    }
}

void USART2_IRQHandler(void){
    USART_ClearITPendingBit(USART2, USART_IT_RXNE);
    IWire.Write((uint8_t)USART2->DR);
    Uart.Printf("<-- %X\r", (uint8_t)USART2->DR);
}
